/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

extern NSString *const FBSnapshotMaxDepthKey;

/**
 Accessors for Global Constants.
 */
@interface FBConfiguration : NSObject

/*! If set to YES will ask TestManagerDaemon for element visibility */
+ (void)setShouldUseTestManagerForVisibilityDetection:(BOOL)value;
+ (BOOL)shouldUseTestManagerForVisibilityDetection;

/*! If set to YES will use compact (standards-compliant) & faster responses */
+ (void)setShouldUseCompactResponses:(BOOL)value;
+ (BOOL)shouldUseCompactResponses;

/*! If set to YES (which is the default), the app will be terminated at the end of the session, if a bundleId was specified */
+ (void)setShouldTerminateApp:(BOOL)value;
+ (BOOL)shouldTerminateApp;

/*! If shouldUseCompactResponses == NO, is the comma-separated list of fields to return with each element. Defaults to "type,label". */
+ (void)setElementResponseAttributes:(NSString *)value;
+ (NSString *)elementResponseAttributes;

/*! Disables remote query evaluation making Xcode 9.x tests behave same as Xcode 8.x test */
+ (void)disableRemoteQueryEvaluation;

/*! Enables the extended XCTest debug logging. Useful for developemnt purposes */
+ (void)enableXcTestDebugLogs;

/*! Disables attribute key path analysis, which will cause XCTest on Xcode 9.x to ignore some elements */
+ (void)disableAttributeKeyPathAnalysis;

/*! Disables XCTest automated screenshots taking */
+ (void)disableScreenshots;
/*! Enables XCTest automated screenshots taking */
+ (void)enableScreenshots;

/*! Disables XCTest automated videos taking (iOS 17+) */
+ (void)disableScreenRecordings;
/*! Enables XCTest automated videos taking  (iOS 17+) */
+ (void)enableScreenRecordings;

/* The maximum typing frequency for all typing activities */
+ (void)setMaxTypingFrequency:(NSUInteger)value;
+ (NSUInteger)maxTypingFrequency;
+ (NSUInteger)defaultTypingFrequency;

/* Use singleton test manager proxy */
+ (void)setShouldUseSingletonTestManager:(BOOL)value;
+ (BOOL)shouldUseSingletonTestManager;

/* Enforces WDA to verify the presense of system alerts while checking for an active app */
+ (void)setShouldRespectSystemAlerts:(BOOL)value;
+ (BOOL)shouldRespectSystemAlerts;

/**
 * Extract switch value from arguments
 *
 * @param arguments Array of strings with the command-line arguments, e.g. @[@"--port", @"12345"].
 * @param key Switch to look up value for, e.g. @"--port".
 *
 * @return Switch value or nil if the switch is not present in arguments.
 */
+ (NSString* _Nullable)valueFromArguments: (NSArray<NSString *> *)arguments forKey: (NSString*)key;

/**
 The quality of the screenshots generated by the screenshots broadcaster, expressed
 as a value from 0 to 100. The value 0 represents the maximum compression
 (or lowest quality) while the value 100 represents the least compression (or best
 quality). The default value is 25.
 */
+ (NSUInteger)mjpegServerScreenshotQuality;
+ (void)setMjpegServerScreenshotQuality:(NSUInteger)quality;

/**
 Whether to apply orientation fixes to the streamed JPEG images.
 This is an expensive operation and it is disabled by default, so screenshots
 are returned in portrait, but their actual orientation value could still be found in the EXIF
 metadata.
 ! Enablement of this setting may lead to WDA process termination because of an excessive CPU usage.
 */
+ (BOOL)mjpegShouldFixOrientation;
+ (void)setMjpegShouldFixOrientation:(BOOL)enabled;

/**
 The framerate at which the background screenshots broadcaster should broadcast
 screenshots in range 1..60. The default value is 10 (Frames Per Second).
 Setting zero value will cause the framerate to be at its maximum possible value.
 */
+ (NSUInteger)mjpegServerFramerate;
+ (void)setMjpegServerFramerate:(NSUInteger)framerate;

/**
 Whether to limit the XPath scope to descendant items only while performing a lookup
 in an element context. Enabled by default. Being disabled, allows to use XPath locators
 like ".." in order to match parent items of the current context root.
 */
+ (BOOL)limitXpathContextScope;
+ (void)setLimitXpathContextScope:(BOOL)enabled;

/**
 The quality of display screenshots. The higher quality you set is the bigger screenshot size is.
 The highest quality value is 0 (lossless PNG) or 3 (lossless HEIC). The lowest quality is 2 (highly compressed JPEG).
 The default quality value is 3 (lossless HEIC).
 See https://developer.apple.com/documentation/xctest/xctimagequality?language=objc
 */
+ (NSUInteger)screenshotQuality;
+ (void)setScreenshotQuality:(NSUInteger)quality;

/**
 The range of ports that the HTTP Server should attempt to bind on launch
 */
+ (NSRange)bindingPortRange;

/**
 The IP address that the HTTP Server should bind to on launch.
 Returns nil if not specified, which causes the server to listen on all interfaces.
 */
+ (NSString * _Nullable)bindingIPAddress;

/**
 The port number where the background screenshots broadcaster is supposed to run
 */
+ (NSInteger)mjpegServerPort;

/**
 The scaling factor for frames of the mjpeg stream. The default (and maximum) value is 100,
 which does not perform any scaling. The minimum value must be greater than zero.
 ! Setting this to a value less than 100, especially together with orientation fixing enabled
 ! may lead to WDA process termination because of an excessive CPU usage.
 */
+ (CGFloat)mjpegScalingFactor;
+ (void)setMjpegScalingFactor:(CGFloat)scalingFactor;

/**
 YES if verbose logging is enabled. NO otherwise.
 */
+ (BOOL)verboseLoggingEnabled;

/**
 Disables automatic handling of XCTest UI interruptions.
 */
+ (void)disableApplicationUIInterruptionsHandling;

/**
 * Configure keyboards preference to make test running stable
 */
+ (void)configureDefaultKeyboardPreferences;


/**
 * Turn on softwar keyboard forcefully for simulator.
 */
+ (void)forceSimulatorSoftwareKeyboardPresence;

/**
Defines keyboard preference enabled status
*/
typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) {
    FBConfigurationKeyboardPreferenceDisabled = 0,
    FBConfigurationKeyboardPreferenceEnabled = 1,
    FBConfigurationKeyboardPreferenceNotSupported = 2,
};

/**
 * Modify keyboard configuration of 'auto-correction'.
 *
 * @param isEnabled Turn the configuration on if the value is YES
 */
+ (void)setKeyboardAutocorrection:(BOOL)isEnabled;
+ (FBConfigurationKeyboardPreference)keyboardAutocorrection;

/**
 * Modify keyboard configuration of 'predictive'
 *
 * @param isEnabled Turn the configuration on if the value is YES
 */
+ (void)setKeyboardPrediction:(BOOL)isEnabled;
+ (FBConfigurationKeyboardPreference)keyboardPrediction;

/**
 Sets maximum depth for traversing elements tree from parents to children while requesting XCElementSnapshot.
 Used to set maxDepth value in a dictionary provided by XCAXClient_iOS's method defaultParams.
 The original XCAXClient_iOS maxDepth value is set to INT_MAX, which is too big for some queries
 (for example: searching elements inside a WebView).
 Reasonable values are from 15 to 100 (larger numbers make queries slower).

 @param maxDepth The number of maximum depth for traversing elements tree
 */
+ (void)setSnapshotMaxDepth:(int)maxDepth;

/**
  @return The number of maximum depth for traversing elements tree
 */
+ (int)snapshotMaxDepth;

/**
 * Whether to use fast search result matching while searching for elements.
 * By default this is disabled due to https://github.com/appium/appium/issues/10101
 * but it still makes sense to enable it for views containing large counts of elements
 *
 * @param enabled Either YES or NO
 */
+ (void)setUseFirstMatch:(BOOL)enabled;
+ (BOOL)useFirstMatch;

/**
 * Whether to bound the lookup results by index.
 * By default this is disabled and bounding by accessibility is used.
 * Read https://stackoverflow.com/questions/49307513/meaning-of-allelementsboundbyaccessibilityelement
 * for more details on these two bounding methods.
 *
 * @param enabled Either YES or NO
 */
+ (void)setBoundElementsByIndex:(BOOL)enabled;
+ (BOOL)boundElementsByIndex;

/**
 * Modify reduce motion configuration in accessibility.
 * It works only for Simulator since Real device has security model which allows chnaging preferences
 * only from settings app.
 *
 * @param isEnabled Turn the configuration on if the value is YES
 */
+ (void)setReduceMotionEnabled:(BOOL)isEnabled;
+ (BOOL)reduceMotionEnabled;

/**
 * Set the idling timeout. If the timeout expires then WDA
 * tries to interact with the application even if it is not idling.
 * Setting it to zero disables idling checks.
 * The default timeout is set to 10 seconds.
 *
 * @param timeout The actual timeout value in float seconds
 */
+ (void)setWaitForIdleTimeout:(NSTimeInterval)timeout;
+ (NSTimeInterval)waitForIdleTimeout;

/**
 * Set the idling timeout for different actions, for example events synthesis, rotation change,
 * etc. If the timeout expires then WDA tries to interact with the application even if it is not idling.
 * Setting it to zero disables idling checks.
 * The default timeout is set to 2 seconds.
 *
 * @param timeout The actual timeout value in float seconds
 */
+ (void)setAnimationCoolOffTimeout:(NSTimeInterval)timeout;
+ (NSTimeInterval)animationCoolOffTimeout;

/**
 Enforces the page hierarchy to include non modal elements,
 like Contacts. By default such elements are not present there.
 See https://github.com/appium/appium/issues/13227

 @param isEnabled Set to YES in order to enable non modal elements inclusion.
 Setting this value to YES will have no effect if the current iOS SDK does not support such feature.
 */
+ (void)setIncludeNonModalElements:(BOOL)isEnabled;
+ (BOOL)includeNonModalElements;

/**
 Sets custom class chain locators for accept/dismiss alert buttons location.
 This might be useful if the default buttons detection algorithm fails to determine alert buttons properly
 when defaultAlertAction is set.

 @param classChainSelector Valid class chain locator, which determines accept/reject button
 on the alert. The search root is the alert element itself.
 Setting this value to nil or an empty string (the default
 value) will enforce WDA to apply the default algorithm for alert buttons location.
 If an invalid/non-parseable locator is set then the lookup will fallback to the default algorithm and print a
 warning into the log.
 Example: ** /XCUIElementTypeButton[`label CONTAINS[c] 'accept'`]
 */
+ (void)setAcceptAlertButtonSelector:(NSString *)classChainSelector;
+ (NSString *)acceptAlertButtonSelector;
+ (void)setDismissAlertButtonSelector:(NSString *)classChainSelector;
+ (NSString *)dismissAlertButtonSelector;

/**
 Sets class chain selector to apply for an automated alert click
 */
+ (void)setAutoClickAlertSelector:(NSString *)classChainSelector;
+ (NSString *)autoClickAlertSelector;

/**
 * Whether to use HIDEvent for text clear.
 * By default this is enabled and HIDEvent is used for text clear.
 *
 * @param enabled Either YES or NO
 */
+ (void)setUseClearTextShortcut:(BOOL)enabled;
+ (BOOL)useClearTextShortcut;

#if !TARGET_OS_TV
/**
 Set the screenshot orientation for iOS

 It helps to fix the screenshot orientation when the device under test's orientation changes.
 For example, when a device changes to the landscape, the screenshot orientation could be wrong.
 Then, this setting can force change the screenshot orientation.
 Xcode versions, OS versions or device models and simulator or real device could influence it.

 @param orientation Set the orientation to adjust the screenshot.
 Case insensitive "portrait", "portraitUpsideDown", "landscapeRight" and "landscapeLeft"  are available
 to force the coodinate adjust. Other words are handled as "auto", which handles
 the adjustment automatically. Defaults to "auto".
 @param error If no availale orientation strategy was given, it returns an NSError object that describes the problem.
 */
+ (BOOL)setScreenshotOrientation:(NSString *)orientation error:(NSError **)error;

/**
@return The value of UIInterfaceOrientation
*/
+ (NSInteger)screenshotOrientation;

/**
@return The orientation as String for human read
*/
+ (NSString *)humanReadableScreenshotOrientation;

#endif

/**
 Resets all session-specific settings to their default values
 */
+ (void)resetSessionSettings;

/**
 * Whether to calculate `hittable` attribute using native APIs
 * instead of legacy heuristics.
 * This flag improves accuracy, but may affect performance.
 * Disabled by default.
 *
 * @param enabled Either YES or NO
 */
+ (void)setIncludeHittableInPageSource:(BOOL)enabled;
+ (BOOL)includeHittableInPageSource;

/**
 * Whether to include `nativeFrame` attribute in the XML page source.
 *
 * When enabled, the XML representation will contain the precise rendered
 * frame of the UI element.
 *
 * This value is more accurate than the legacy `wdFrame`, which applies rounding
 * and may introduce inconsistencies in size and position calculations.
 *
 * The value is disabled by default to avoid potential performance overhead.
 *
 * @param enabled Either YES or NO
 */
+ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled;
+ (BOOL)includeNativeFrameInPageSource;

/**
 * Whether to include `minValue`/`maxValue` attributes in the page source.
 * These attributes are retrieved from native element snapshots and represent
 * value boundaries for elements like sliders or progress indicators.
 * This may affect performance if used on many elements.
 * Disabled by default.
 *
 * @param enabled Either YES or NO
 */
+ (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled;
+ (BOOL)includeMinMaxValueInPageSource;

@end

NS_ASSUME_NONNULL_END
